from django.http import HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import render,HttpResponse
from detectorTools import immediatelyJudge as Judger
from detectorTools import useHmmModel as hmmJudger
from detectorTools import useSvmModel as svmJudger
from myDefensor.models import ArgValueSubmit,xssInput
from detectorTools import strategy,offlineJob
from myDetector.models import markedValue,trainningPool
from html.parser import HTMLParser
from math import sqrt
# from django.core.paginator import Paginator
import json
import math
import getData
import datetime
import os
import re
# Create your views here.
def mainDealer(request):
	# 仅仅完成了对参数值的初步模型判断
	# post = request.POST.items()
	print("rawTarget =",request.POST["rawTarget"])
	target = reverse("myDetector:tempTest")+'?'
	argName = request.POST["paramName"]
	argPath = argName.split("?")[0]
	argName = argName.split("?")[1]
	# dealt by model
	lmModel = Judger.readModelFromFile(name = Judger.getFileName(argName,"2018119","lm"),obj_hook = Judger.lmFromFile)
	cmModel = Judger.readModelFromFile(name = Judger.getFileName(argName,"2018119","cm"),obj_hook = Judger.cmFromFile)
	lmPredictRst = lmModel.predict(samples=[request.POST["paramValue"]],realRst=[])
	cmPredictRst = cmModel.predict(samples=[request.POST["paramValue"]],realRst=[])
	judgeRst = {"lm":lmPredictRst[0],"cm":cmPredictRst[0]}
	if not judgeRst["lm"]:
		addNewMarkedValue(argName, request.POST["paramValue"], "lm", argPath)
	if not judgeRst["cm"]:
		addNewMarkedValue(argName, request.POST["paramValue"], "cm", argPath)
	# 
	request.session["argName"] = argName
	request.session["argPath"] = argPath
	request.session["argValue"] = request.POST["paramValue"]
	request.session["ip"] = request.META['REMOTE_ADDR']
	request.session["judgeRst"] = judgeRst
	request.session["rawTarget"] = request.POST["rawTarget"]
	target = target[:-1]
	return HttpResponseRedirect(target)

def tempTest(request):
	# 提交的数据仅仅是被存在了argValueSubmit表中
	cont = '<p>argName = '+request.session["argName"]+"</p> <p>argValue = "+request.session["argValue"]+"</p>"
	cont = cont + "<p>remoteIP = "+request.session["ip"]+"</p> <p>argPath="+ request.session["argPath"]+"</p>"
	print("console:",cont)
	# start handliing args
	argValue = request.session["argValue"]
	argName = request.session["argName"]
	argPath = request.session["argPath"]
	remoteIp = request.session["ip"]
	judgeRst = request.session["judgeRst"]
	judgeType = "lmRst:"+str(judgeRst["lm"])+";cmRst:"+str(judgeRst["cm"])
	rawTarget = request.session["rawTarget"]
	hint = strategy.responseStrategy(judgeRst)
	# save info as sample
	Arg = ArgValueSubmit(route = argPath,arg_name = argName,source_ip = remoteIp,type_judgement=judgeType,value = argValue,value_len = argValue.__len__())
	Arg.save()
	# end handling args
	del request.session["argValue"]
	del request.session["argName"]
	del request.session["ip"]
	del request.session["argPath"]
	del request.session["rawTarget"]
	request.session["hint"] = hint
	return HttpResponseRedirect(reverse("myDefensor:argShow"))

def showModels(request):
	date = '2018119'
	modelType = request.GET["modelType"]
	paramPath = request.GET["paramPath"]
	target = request.GET["target"]
	modelName = target+"_"+date+"_"+modelType
	judgeModel = None
	needImg = False
	fileName = Judger.getFileName(target,date,modelType)
	infoList = []
	if modelType == 'lm':
		judgeModel = Judger.readModelFromFile(fileName, obj_hook = Judger.lmFromFile) 
		infoList.append(("var",judgeModel.getVar()))
		infoList.append(("mean",judgeModel.getMean()))
		infoList.append(("stdev",judgeModel.getStdev()))
		for pct in range(5,100,5):
			infoList.append(("pct="+str(pct),sensitiveLengthRange(judgeModel.getMean(), judgeModel.getStdev(), pct)))
		avs = ArgValueSubmit.objects.filter(arg_name = target).filter(route = paramPath).filter(type_judgement__contains = "lmRst:1").filter(confirmed = 'false')

	elif modelType == 'cm':
		judgeModel = Judger.readModelFromFile(fileName,obj_hook = Judger.cmFromFile)
		infoList.append(("ICDList",judgeModel.getICDList()))
		needImg = True	
		avs = ArgValueSubmit.objects.filter(arg_name = target).filter(route = paramPath).filter(type_judgement__contains = "cmRst:1").filter(confirmed = 'false')
	markedData = markedValue.objects.filter(route = paramPath).filter(arg_name = target).filter(judger = modelType)
	if(len(markedData) != 0):
		markedData = list(markedData.values_list('value',flat = True))
	else:
		markedData=["No Datas"]

	if(len(avs) != 0):
		avs = list(avs.values_list('value',flat = True))
	else:
		avs=["No Datas"]

	context = {
	"modelInfo":infoList,"modelName":modelName,
	"markedValue":markedData,"paramName":target,
	"modelType":modelType,"needImg":needImg,
	"paramPath":paramPath,"nowPage":1,
	"submitValue":avs,"needHJRst":isThereHJRecord(target)
	}
	return render(request,"myDetector/displayModel.html",context)

def dealMv(request):
	param = json.loads(bytes.decode(request.body))
	myParser = HTMLParser() 
	fld = myParser.unescape(param["paramName"])
	value = myParser.unescape(param["value"])
	modelType = myParser.unescape(param["modelType"])
	op = myParser.unescape(param["op"])
	if op == "del":
		mv = markedValue.objects.filter(arg_name = fld).filter(value = value).filter(judger = modelType)
	elif op == "confirm":
		mv = ArgValueSubmit.objects.filter(arg_name = fld).filter(value = value).filter(type_judgement__contains = modelType+"Rst:1").filter(confirmed = "false")
	for x in mv:
		tp = trainningPool(route = x.route,arg_name = x.arg_name,value = x.value)
		tp.save()
	if op == "del":	
		mv.delete()
	elif op == "confirm":
		mv.update(confirmed = "true")
	response = "success"
	resp = {}
	resp["response"] = response
	resp["op"] = op
	return HttpResponse(json.dumps(resp),content_type = 'application/json')
def reTrain(request):
	param = json.loads(bytes.decode(request.body))
	myParser = HTMLParser() 
	paramName = myParser.unescape(param["paramName"])
	modelType = myParser.unescape(param["modelType"])
	op = myParser.unescape(param["op"])
	print(paramName,modelType,op)
	if(modelType =="lm"):
		Judger.offlineTrainingAndSave(fld = paramName,modelType="lenModel",baseTable="mydetector_trainningpool")
	elif(modelType =="cm"):
		Judger.offlineTrainingAndSave(fld = paramName,modelType="charModel",baseTable="mydetector_trainningpool")
	response = "success"
	resp = {}
	resp["response"] = response
	resp["op"] = op
	return HttpResponse(json.dumps(resp),content_type = 'application/json')

def readMLClassificationRst(request):
	paramName = request.GET['paramName']
	route = request.GET['route']
	docContent = None
	with open(offlineJob.FILE_PATH_HJ+paramName+".txt","r") as f:
		docContent = json.loads(f.read())

	context = {"class_one":docContent["0"],"class_two":docContent["1"],"route":route,"paramName":paramName}
	return render(request,"myDetector/machineClassificationRst.html",context)
def dealMLClassificationRst(request):
	param = json.loads(bytes.decode(request.body))
	myParser = HTMLParser() 
	paramName = myParser.unescape(param["paramName"])
	op = myParser.unescape(param["op"])
	value = myParser.unescape(param["value"])
	route = myParser.unescape(param["route"])
	pos = myParser.unescape(param["pos"])
	print(type(pos),pos)
	if op == "confirmBad":
		mkv = markedValue.objects.filter(route = route).filter(arg_name = paramName).filter(value = value)
		print("len:",mkv.__len__())
		if mkv.__len__() == 0:
			addNewMarkedValue(paramName, value,"mankind", route)
			
	elif op == "confirmGood":
		tp = trainningPool(route = route, arg_name = paramName, value = value)
		tp.save()
	with open(offlineJob.FILE_PATH_HJ+paramName+".txt","r") as f:
		docContent = json.loads(f.read())
		docContent[pos].remove(value)
	with open(offlineJob.FILE_PATH_HJ+paramName+".txt","w") as f:
		f.write(json.dumps(docContent))
	avs = ArgValueSubmit.objects.filter(route = route).filter(arg_name = paramName).filter(value = value).filter(confirmed = 'false')
	avs.update(confirmed = 'true')

	response = "success"
	resp = {}
	resp["response"] = response
	return HttpResponse(json.dumps(resp),content_type = 'application/json')
# def paginatorForMarkedValue(request):
	# 目前这个写法不考虑性能只是简单地分页实现。按道理说不应该一次把所有的内容都查出来。
	# target = request.GET["target"]
	# path = request.GET["path"]
	# modelType = request.GET["modelType"]	
	# pageIndex = request.GET["pageIndex"]
	# queryList = markedValue.objects.filter(route = path).filter(arg_name = target).filter(judger = modelType).order_by("id")
	# myPaginator = Paginator(queryList,1)
	# print(myPaginator.page(pageIndex).object_list[0])

	# return HttpResponse({"a":"success","context":myPaginator},content_type = 'application/json')

def xssIntoDb(request):
	spliter = re.compile(r';')
	filePath = "C:\\Users\\LENOVO\\Desktop\\machineLearning\\Code\\testSite\\myDetector\\detectorTools\\xssRecord\\"
	title = request.POST['title']
	value = request.POST['inputText']
	articles = spliter.split(value)
	hmmRst = hmmJudger.test(hmmJudger.hmmclf,articles)
	svmDatas = list()
	svmMalicious = list()
	svmJudger.etl(articles,svmDatas)
	svmPredict = svmJudger.svmclf.predict(svmDatas)
	svmJudger.getMaliciousString(articles, svmPredict, svmMalicious)
	print(svmMalicious)
	print(hmmRst)
	svmSummary = "svm("+str(len(svmMalicious))+")"
	hmmSummary = "hmm("+str(len(hmmRst))+")"
	xss = xssInput(title = title,value = value,model_one_summary = svmSummary,model_two_summary = hmmSummary,
		model_one_target = str(svmMalicious),model_two_target = str(hmmRst),state = 'unChecked')
	xss.save()
	return HttpResponseRedirect(reverse("myDetector/xssDetectorPage"))
def xssDetectorPage(request):
	xssRst = xssInput.objects.all()
	context = {"xssRst":xssRst}
	return render(request,"myDetector/xssJudger.html",context)

def readXss(request):
	xssId = request.GET['id']
	xssContent = xssInput.objects.filter(id = xssId)
	svmList = list(xssContent.values_list('model_one_target',flat = True))
	hmmList = list(xssContent.values_list('model_two_target',flat = True))
	print(type(svmList),svmList)
	print(type(hmmList),len(hmmList))
	hmmList =  hmmList[0][1:-1].split(',')
	svmList =  svmList[0][1:-1].split(',')
	print(svmList)
	if str(hmmList) == "['']" :
		hmmList = ["None"]
	if str(svmList) == "['']" :
		svmList = ["None"]
	context = {'hmmList':hmmList,'svmList':svmList}
	return render(request,'myDetector/readXss.html',context)
def xssStateChange(request):
	print(request.GET['id'],request.GET['op'])
	xssInput.objects.filter(id = request.GET['id']).update(state = request.GET['op'])
	response = "success"
	resp = {}
	resp["response"] = response
	return HttpResponse(json.dumps(resp),content_type = 'application/json')
# tools
def addNewMarkedValue(paramName,value,judger,route):
	newMv = markedValue(arg_name=paramName,value=value,judger=judger,route = route,)
	newMv.save()
def sensitiveLengthRange(mean,stdev,pct):
	m = int(sqrt(1 / (1 - pct * 0.01)))
	bottom = mean - m * stdev
	top = mean + m * stdev
	return "bottom="+str(math.ceil(bottom))+";top="+str(math.floor(top))
def isThereHJRecord(argname):
	argname = argname+".txt"
	fileList = os.listdir(offlineJob.FILE_PATH_HJ)
	rst = False
	if argname in fileList:
		rst = True
	return rst


